package com.ease.map.tile {
    import com.gskinner.motion.GTween;
    import com.ease.map.Map;
    import com.ease.map.common.basetype.linkedlist.LinkedListBitmapNode;
    import com.ease.map.geometry.basetype.Extent;
    import com.ease.map.geometry.basetype.Pixel;
    import com.ease.map.geometry.basetype.Size;
    import com.ease.map.layer.Grid;
    import com.ease.map.layer.Layer;
    import com.ease.map.request.DataRequest;
    import flash.display.Bitmap;
    import flash.display.Loader;
    import flash.display.LoaderInfo;
    import flash.events.Event;
    import flash.events.IOErrorEvent;
    import flash.net.URLRequestMethod;
    import flash.net.URLVariables;
    import com.ease.map.tile.Tile;

    /**
     * 图片瓦片类 ，用于 wms、wms-c、wmts等图片
     */
    public class ImageTile extends Tile {
        private var _attempt:Number = 0;

        private var _queued:Boolean = false;

        private var _request:DataRequest = null;

        private var _method:String = null;

        [Bindable]
        [Embed(source="/assets/images/kgis.png")]
        private var kgisMapImage:Class;

        public function ImageTile(layer:Layer, position:Pixel, bounds:Extent, url:String, size:Size) {
            super(layer, position, bounds, url, size);
            // 否则会看到瓦片间的缝隙
            this.cacheAsBitmap = false;
        }

        override public function destroy():void {
            this.clear();

            if (this.layer.contains(this))
                this.layer.removeChild(this);
            if (_request)
                _request.destroy();

            super.destroy();
        }

        /**
         * 绘制瓦片
         */
        override public function draw():void {

            if (_drawPosition != null) {
                this.bounds = this.getBoundsFromTopLeftPixel(_drawPosition);
            }
            else {
                this.bounds = this.getBoundsFromTopLeftPixel(position);
            }

            if (!withinMapBounds()) {
                return;
            }

            if (this.url == null) {
                this.url = this.layer.getURL(this.bounds);

                if (this.url == null) {
                    return;
                }
            }

            var cachedBitmap:Bitmap;
            if ((this.layer is Grid) && ((cachedBitmap = (this.layer as Grid).getTileCache(this.url)) != null)) {
                drawLoader(this.url, cachedBitmap, true);
            }
            else {
                if (_request) {
                    _request.destroy();
                }
                this.loading = true;
                _request = new DataRequest(this.url, onTileLoadEnd, onTileLoadError, method);
                if (_request.method == URLRequestMethod.POST) {
                    _request.postContent = new URLVariables(this.url);
                }

                _request.proxy = this.layer.proxy;
                _request.send();

            }
        }

        public function onTileLoadEnd(event:Event):void {
            var loaderInfo:LoaderInfo = event.target as LoaderInfo;
            var loader:Loader = loaderInfo.loader as Loader;
            var bitmap:Bitmap = Bitmap(loader.content);
            drawLoader(loader.name, bitmap, false);
        }

        /**
         * Method to draw the loader (recently loaded or cached)
         *
         * @param url The tile url
         * @param bitmap The bitmap to draw
         * @param cached Cached loader or not
         */
        private function drawLoader(url:String, bitmap:Bitmap, cached:Boolean):void {
            if (this.layer) {
                if (_drawPosition != null) {
                    this.position = _drawPosition;
                    _drawPosition = null;
                }

                bitmap.width = this.size.w;
                bitmap.height = this.size.h;

                var i:int = this.numChildren - 1;
                for (i; i > -1; i--) {
                    this.removeChildAt(i);
                }
                this.addChildAt(bitmap, 0);

                if (!this.layer.contains(this)) {
                    this.layer.addChild(this);
                }
                if (this.layer.tweenOnLoad)
                    var tw:GTween = new GTween(this, 0.5, {alpha: 1});

                this.drawn = true;
                this.loading = false;

                // We put the loader into the cache if it's a recently loaded
                if ((this.layer is Grid) && (!cached)) {
                    var node:LinkedListBitmapNode = new LinkedListBitmapNode(bitmap, url);
                    (this.layer as Grid).addTileCache(node);
                }
            }
        }

        public function onTileLoadError(event:IOErrorEvent):void {
            if ((!this.layer) || (!this.layer.map) || (++this._attempt <= Map.IMAGE_RELOAD_ATTEMPTS)) {
                // Retry loading
                trace("ImageTile - onTileLoadError: Error while loading tile " + this.url + " ; retry #" + this._attempt);
                this.draw();
            }
            else {
                // Maximum number of tries reached
                trace("ImageTile - onTileLoadError: Error while loading tile " + this.url);
                //this.loading = false;

                var bitmap:Bitmap = Bitmap(new kgisMapImage());
                drawLoader(this.url, bitmap, false);

            }
        }

        /**
         *  Clear the tile of any bounds/position-related data
         */
        override public function clear():void {
            super.clear();

            if (this.layer.tweenOnLoad)
                this.alpha = 0;

            if (this._request) {
                _request.destroy();
            }

            var i:int = this.numChildren - 1;
            for (i; i > -1; i--) {
                removeChildAt(i);
            }
        }

        //Getters and Setters
        public function get queued():Boolean {
            return this._queued;
        }

        public function set queued(value:Boolean):void {
            this._queued = value;
        }


        public function get method():String {
            return this._method;
        }

        public function set method(value:String):void {
            this._method = value;

        }


    }
}

